#ifndef __COLOR_H__
#define __COLOR_H__

#include <assert.h>
#include "BasicType/BasicType_1.h"

namespace GCRE {
	namespace BasicType {

		class Color4f;

		class Color4b {
			friend Color4f;

			public:
				explicit Color4b( SFByte r, SFByte g, SFByte b, SFByte a );
				Color4b( SFInt r, SFInt g, SFInt b, SFInt a );
				Color4b( SFFloat r, SFFloat g, SFFloat b, SFFloat a );
				Color4b( const Color4b& c );
				Color4b( const Color4f & c );
				~Color4b();

				void								Set( SFByte r, SFByte g, SFByte b, SFByte a );
				void								Set( SFInt r, SFInt g, SFInt b, SFInt a );
				void								Set( SFFloat r, SFFloat g, SFFloat b, SFFloat a );
				const SFByte*				GetData() const;
				SFByte							r() const;
				SFByte							g() const;
				SFByte							b() const;
				SFByte							a() const;

				SFByte							operator[]( SFInt i ) const;
				SFByte&						operator[]( SFInt i );
				Color4b&						operator=( const Color4b& c );
				Color4b&						operator=( const Color4f& c );
				Color4b&						operator+=( const Color4b& c );
				Color4b&						operator+=( const Color4f& c );
				Color4b&						operator-=( const Color4b& c );
				Color4b&						operator-=( const Color4f& c );
				Color4b&						operator*=( SFFloat s );
				Color4b						operator+( const Color4b& c ) const;
				Color4b						operator+( const Color4f& c ) const;	
				Color4b						operator-( const Color4b& c ) const;
				Color4b						operator-( const Color4f& c ) const;
				Color4b						operator*( SFFloat s ) const;
				friend Color4b				operator*( SFFloat s, const Color4b& c );

			protected:

			private:
				union {
					SFByte data[4];
					struct {
						SFByte R, G, B, A;
					};
				};
		};

		inline void Color4b::Set( SFByte r, SFByte g, SFByte b, SFByte a )
		{
			R = r; G = g; B = b; A = a;
		}

		inline const SFByte* Color4b::GetData() const { return data; }
		inline SFByte Color4b::r() const { return R; }
		inline SFByte Color4b::g() const { return G; }
		inline SFByte Color4b::b() const { return B; }
		inline SFByte Color4b::a() const { return A; }
		inline SFByte Color4b::operator[]( SFInt i ) const { assert( i >= 0 && i < 4 ); return data[i]; }
		inline SFByte& Color4b::operator[]( SFInt i ) { assert( i >= 0 && i < 4 ); return data[i]; }


		class Color4f {
			friend Color4b;

			public:
				explicit Color4f( SFFloat r, SFFloat g, SFFloat b, SFFloat a );
				Color4f( SFInt r, SFInt g, SFInt b, SFInt a );
				Color4f( const Color4b& c );
				Color4f( const Color4f& c );
				~Color4f();

				void							Set( SFFloat r, SFFloat g, SFFloat b, SFFloat a );
				void							Set( SFInt r, SFInt g, SFInt b, SFInt a );
				const SFFloat*			GetData() const;
				SFFloat						r() const;
				SFFloat						g() const;
				SFFloat						b() const;
				SFFloat						a() const;

				SFFloat						operator[]( SFInt i ) const;
				SFFloat&					operator[]( SFInt i );
				Color4f&					operator=( const Color4f& c );
				Color4f&					operator=( const Color4b& c );
				Color4f&					operator+=( const Color4f& c );
				Color4f&					operator+=( const Color4b& c );
				Color4f&					operator-=( const Color4f& c );
				Color4f&					operator-=( const Color4b& c );
				Color4f&					operator*=( SFFloat s );
				Color4f						operator+( const Color4f& c ) const;
				Color4f						operator+( const Color4b& c ) const;
				Color4f						operator-( const Color4f& c ) const;
				Color4f						operator-( const Color4b& c ) const;
				Color4f						operator*( SFFloat s ) const;
				friend Color4f			operator*( SFFloat s , const Color4f& c );

			protected:

			private:
				union {
					SFFloat data[4];
					struct {
						SFFloat R, G, B, A;
					};
				};
		};

		inline const SFFloat* Color4f::GetData() const { return data; }
		inline SFFloat Color4f::r() const { return R; }
		inline SFFloat Color4f::g() const { return G; }
		inline SFFloat Color4f::b() const { return B; }
		inline SFFloat Color4f::a() const { return A; }
		inline SFFloat Color4f::operator[]( SFInt i ) const { assert( i >= 0 && i < 4 ); return data[i]; }
		inline SFFloat& Color4f::operator[]( SFInt i ) { assert( i >= 0 && i < 4 ); return data[i]; }

	}
}

#endif	//	__COLOR_H__